package gobase

import (
	"fmt"
	"gitee.com/ymofen/gobase/gocache"
	"os"
	"strconv"
	"strings"
)

type TFactoryVarFunc = func(sender interface{}, args ...interface{}) interface{}
type t_createfun func(args ...interface{}) (rval interface{}, err error)

//
//	type varFactory struct {
//		lock      *sync.RWMutex
//		varMap    map[string]interface{}
//		createMap map[string]t_createfun
//	}
//
// var (
//
//	defFactory *varFactory
//
// )
//
//	func init() {
//		defFactory = newVarFactory()
//	}
//
//	func newVarFactory() *varFactory {
//		rval := &varFactory{
//			lock:      new(sync.RWMutex),
//			varMap:    make(map[string]interface{}),
//			createMap: make(map[string]t_createfun),
//		}
//		return rval
//	}
//
// // 注册一个创建方法函数
//
//	func RegisterFactoryCreateFunc(id string, cfun t_createfun) error {
//		defFactory.lock.Lock()
//		defer defFactory.lock.Unlock()
//		if defFactory.createMap[id] != nil {
//			fmt.Fprintf(os.Stderr, "%s is registed\n", id)
//			return errors.New(id + " is registed!")
//		}
//		defFactory.createMap[id] = cfun
//		return nil
//	}
//
// // 移除一个创建方法
//
//	func UnregisterFactoryCreateFunc(id string) {
//		defFactory.lock.Lock()
//		defer defFactory.lock.Unlock()
//		delete(defFactory.createMap, id)
//		return
//	}
//
// // 使用方法创建一个对象
//
//	func CreateFactoryInstance(id string, args ...interface{}) (rval interface{}, err error) {
//		defFactory.lock.RLock()
//		f := defFactory.createMap[id]
//		if f == nil {
//			defFactory.lock.RUnlock()
//			return nil, fmt.Errorf("[%s]未注册创建方法", id)
//		}
//		defFactory.lock.RUnlock()
//
//		return f(args...)
//	}
//
// // 获取一个全局对象
//
//	func GetFactoryVar(id string) interface{} {
//		defFactory.lock.RLock()
//		defer defFactory.lock.RUnlock()
//		return defFactory.varMap[id]
//	}
//
// // 注册一个全局对象
//
//	func RegisterFactoryVar(id string, val interface{}) {
//		defFactory.lock.Lock()
//		defer defFactory.lock.Unlock()
//		defFactory.varMap[id] = val
//	}
//
// // 移除一个全局对象
//
//	func RemoveFactoryVar(id string) {
//		defFactory.lock.Lock()
//		defer defFactory.lock.Unlock()
//		delete(defFactory.varMap, id)
//	}
//
// // 循环所有的全局对象
// //
// //	cb 返回false 则终止循环
//
//	func RangeFactoryVarList(cb func(val interface{}) bool) {
//		defFactory.lock.RLock()
//		defer defFactory.lock.RUnlock()
//		for _, itm := range defFactory.varMap {
//			if cb(itm) {
//				break
//			}
//		}
//	}
//
//	func RangeFactoryVarListEx(cb func(key string, val interface{}) bool) {
//		defFactory.lock.RLock()
//		defer defFactory.lock.RUnlock()
//		for key, val := range defFactory.varMap {
//			if cb(key, val) {
//				break
//			}
//		}
//	}

func TryGetFactoryTokenValue(token string) (string, bool) {
	if key, ok := TryTrimPrefix(token, "$env."); ok {
		return os.Getenv(key), true
	} else if key, ok = TryTrimPrefix(token, "$cache."); ok {
		if v, ok1 := gocache.Get(key); ok1 {
			if fn, ok1 := v.(TFactoryVarFunc); ok1 {
				v = fn(nil)
			}
			return GetStrValue(v, ""), true
		} else {
			return "", false
		}
	} else if key, ok = TryTrimPrefix(token, "$"); ok {
		v := GetFactoryVar(key)
		if fn, ok1 := v.(TFactoryVarFunc); ok1 {
			v = fn(nil)
		}

		return GetStrValue(v, ""), true
	}
	return token, false
}

func innerParseTokens(expTokens []string, getTokenValue func(k string) (v string, ok bool)) []string {
	for {
		s1 := expTokens[0]
		if len(s1) == 0 {
			break
		}
		if len(expTokens) < 2 {
			break
		}
		ops := expTokens[1]
		if ops == "hash" {
			v1, _ := getTokenValue(s1)
			d1 := HashStr(v1)
			expTokens[0] = fmt.Sprintf("%d", d1)
			expTokens = append(expTokens[:1], expTokens[2:]...)
		} else if ops == "%" || ops == "mod" {
			if len(expTokens) < 3 { // 缺少第三个数据
				return []string{"invalid [mod] args"}
			}

			v1, _ := getTokenValue(s1)

			i1, err := strconv.ParseInt(v1, 10, 64)
			if err != nil {
				return []string{fmt.Sprintf("invalid [mod] args:%s", v1)}
			}

			i2, err := strconv.ParseInt(expTokens[2], 10, 64)
			if err != nil {
				return []string{fmt.Sprintf("invalid [mod] args:%s", expTokens[2])}
			}

			d1 := i1 % i2
			expTokens[0] = fmt.Sprintf("%d", d1)
			expTokens = append(expTokens[:1], expTokens[3:]...)
		} else if ops == "spidx" {
			if len(expTokens) < 4 { //
				return []string{"spidxerr"}
			}

			v1, _ := TryGetFactoryTokenValue(s1)
			sep := expTokens[2]
			if len(sep) == 0 {
				return []string{"spidx miss sep"}
			}
			strs := strings.Split(v1, sep)

			idxstr := expTokens[3]
			idx, err := strconv.ParseInt(idxstr, 10, 64)
			maxl := int64(len(strs))
			if err != nil {
				if idxstr == "last" {
					idx = maxl - 1
				}
			}

			if idx < 0 || idx >= maxl {
				return []string{"spidxerr"}
			}

			expTokens[0] = strs[idx]
			expTokens = append(expTokens[:1], expTokens[4:]...)

		} else if ops == "splastidx" {
			if len(expTokens) < 4 { //
				return []string{"splastidx"}
			}

			v1, _ := TryGetFactoryTokenValue(s1)
			sep := expTokens[2]
			if len(sep) == 0 {
				return []string{"splastidx miss sep"}
			}
			strs := strings.Split(v1, sep)

			idxstr := expTokens[3]
			idx := StrToIntDef(idxstr, -1)
			if idx == -1 {
				return []string{"splastidxerr"}
			}
			maxl := len(strs)
			idx = maxl - 1 - idx
			if idx < 0 || idx >= maxl {
				return []string{"splastidxerr"}
			}

			expTokens[0] = strs[idx]
			expTokens = append(expTokens[:1], expTokens[4:]...)
		} else {
			return []string{fmt.Sprintf("%s unkown", ops)}
		}
	}

	return expTokens
}

// $env.v hash % 10
// $var % 10
// algs-stapull-7bfc46d877-v9hls spidx ' ' 0
func ParseSimpleExp(exp string) (v string, ok bool) {
	expTokens := ParseTokens(exp, ' ')
	if len(expTokens) < 2 {
		return
	}

	expTokens = innerParseTokens(expTokens, TryGetFactoryTokenValue)

	if len(expTokens) == 1 {
		return expTokens[0], true
	}
	return
}

// v
// $env.v hash % 10
// $var % 10
// algs-stapull-7bfc46d877-v9hls spidx ' ' 0
func ParseSimpleExpressionAndVar(exp string) (v string, ok bool) {
	expTokens := ParseTokens(exp, ' ')
	if len(expTokens) == 1 { // 只有一个
		if v1, ok1 := TryGetFactoryTokenValue(expTokens[0]); ok1 {
			return v1, true
		} else {
			return exp, true
		}
	}

	expTokens = innerParseTokens(expTokens, TryGetFactoryTokenValue)

	if len(expTokens) == 1 {
		return expTokens[0], true
	}
	return
}

func ParseSimpleExpWithFunc(exp string, getTokenValue func(k string) (v string, ok bool)) (v string, ok bool) {
	expTokens := ParseTokens(exp, ' ')
	if len(expTokens) == 1 { // 只有一个
		if v1, ok1 := getTokenValue(expTokens[0]); ok1 {
			return v1, true
		} else {
			return exp, true
		}
	}

	expTokens = innerParseTokens(expTokens, getTokenValue)

	if len(expTokens) == 1 {
		return expTokens[0], true
	}
	return
}
